#ifndef SCENEOBJECT_H
#define SCENEOBJECT_H

#include <QVector>
#include <QString>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>


struct Light
{
    QVector4D   _position;
    QVector3D   _intensity;
};


/** Very Simple Object that can be rendered into a Scene.
 *
 *  Mostly assumes that we render a single object and
 *  the corresponding .obj file reader assumes this also.
 *
 *  This code is a continuation from lab3 where it was originally
 *  developed. It handles more edges cases and gives more feedback.
 *
 *  Only minimal protection to the corresponding member variables.
 **/
class SceneObject
{
public:
    SceneObject();
    ~SceneObject();

    void init();
    void setupLighting(Light);
    void createBuffers();
    void createShaderProgram();
    void draw();

    /** This is the function that will be implemented in the Lab.
     *  It reads a simplified version of the WaveFront .obj
     *  format sufficient for use in the OpenGL class.
     *  http://en.wikipedia.org/wiki/Wavefront_.obj_file
     *  http://people.sc.fsu.edu/~jburkardt/data/obj/obj.html
     **/
    void readObjFile(const QString fileName);

    QString & fileName() {return _fileName;}

    QVector<float> & vertices() { return _vertices; }
    int numVertices() const { return _vertices.size()/_numOfVertexComponents; }
    int numVertexComponents() const { return _numOfVertexComponents; }
    const float * verticesData() const { return _vertices.constData(); }

    QVector<float> & normals() { return _normals ; }
    int numNormals() const { return _normals.size()/3; }
    const float * normalsData() const { return _normals.constData(); }

    QVector<float> & textures() { return _textures ; }
    int numTextures() const { return _numOfTextureComponents!=0?_textures.size()/_numOfTextureComponents:_textures.size(); }
    int numTextureComponents() const { return _numOfTextureComponents; }
    const float * texturesData() const { return _textures.constData(); }

    QVector<quint32> & vertexIndices() { return _vertexIndices; }
    int numVertexIndices() const { return _vertexIndices.size()/3; }
    const quint32 * vertexIndicesData() const { return _vertexIndices.constData(); }

    QVector<quint32> & normalIndices() { return _normalIndices ; }
    int numNormalIndices() const { return _normalIndices.size()/3; }
    const quint32 * normalIndicesData() const { return _normalIndices.constData(); }

    QVector<quint32> & textureIndices() { return _textureIndices ; }
    int numTextureIndices() const { return _textureIndices.size()/3; }
    const quint32 * textureIndicesData() const { return _textureIndices.constData(); }

    /** Print debug output to the screen using qDebug() */
    void debugOutput(const int level=0);

    /** Function to be called to create normal vectors because they are often either
     *  missing from obj files or specified as indices and can not directly be used
     **/
    void calculateNormalsFromFaces();


private:
    QString             _fileName;
    QVector<float>      _vertices;
    QVector<float>      _normals;
    QVector<float>      _textures;
    QVector<quint32>    _vertexIndices;
    QVector<quint32>    _normalIndices;
    QVector<quint32>    _textureIndices;

    int     _numOfTextureComponents;
    int     _numOfVertexComponents;


    QOpenGLShaderProgram _shaderProgram;
    QOpenGLBuffer       _vertexBuffer;
    QOpenGLBuffer       _normalBuffer;
    QOpenGLBuffer       _indexBuffer;

    QVector3D   _ambient;
    QVector3D   _diffuse;
    QVector3D   _specular;
    float       _shininess;
};

#endif // SCENEOBJECT_H
